package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.activation.URLDataSource;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;
@Slf4j
public class CAUtil {

  public static String RequestMethod_get = "GET";
  public static String RequestMethod_post = "POST";

  /**
   * 向指定URL发送GET方法的请求
   *
   * @param url 发送请求的URL
   * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
   * @return URL 所代表远程资源的响应结果
   */
  public static String sendGet(String url, String param) {
    String result = "";
    BufferedReader in = null;
    try {
      String urlNameString = url + "?" + param;
      URL realUrl = new URL(urlNameString);
      // 打开和URL之间的连接
      URLConnection connection = realUrl.openConnection();
      // 设置通用的请求属性
      connection.setRequestProperty("accept", "*/*");
      connection.setRequestProperty("connection", "Keep-Alive");
      connection.setRequestProperty(
          "user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
      // 建立实际的连接
      connection.connect();
      // 定义 BufferedReader输入流来读取URL的响应
      //      in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      //      String line;
      //      while ((line = in.readLine()) != null) {
      //        result += line;
      //      }

      System.out.println("====================================================");

      // 流处理
      HttpURLConnection conn = (HttpURLConnection) connection;
      int responseCode = conn.getResponseCode();
      if (responseCode == 200) {
        // 读取返回数据
        StringBuffer strBuf = new StringBuffer();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

        String line = null;
        while ((line = reader.readLine()) != null) {
          strBuf.append(line).append("\n");
        }
        result = strBuf.toString();
        reader.close();
        reader = null;
      } else {
        StringBuffer error = new StringBuffer();
        BufferedReader bufferedReader =
            new BufferedReader(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
        String line1 = null;
        while ((line1 = bufferedReader.readLine()) != null) {
          error.append(line1).append("\n");
        }
        result = error.toString();
        bufferedReader.close();
        bufferedReader = null;
      }

    } catch (Exception e) {
      throw new RuntimeException("调用CA异常" + e.getMessage());
    }
    // 使用finally块来关闭输入流
    finally {
      try {
        if (in != null) {
          in.close();
        }
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
    return result;
  }

  /**
   * 表单提交文件
   *
   * @param urlStr 地址
   * @param textMap 普通参数
   * @param objMap 文件
   * @return
   */
  @SuppressWarnings("rawtypes")
  public static String fileUpload(
      String urlStr, Map<String, String> textMap, Map<String, Object> objMap) {
    String res = "";
    HttpURLConnection conn = null;
    String BOUNDARY = "-----------------12345654321-----------";
    try {
      URL url = new URL(urlStr);
      HostnameVerifier hv =
          new HostnameVerifier() {
            @Override
            public boolean verify(String urlHostName, SSLSession session) {
              System.out.println(
                  "Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
              return true;
            }
          };
      trustAllHttpsCertificates();
      HttpsURLConnection.setDefaultHostnameVerifier(hv);
      conn = (HttpURLConnection) url.openConnection();
      conn.setConnectTimeout(5000);
      conn.setReadTimeout(50000);
      conn.setDoOutput(true);
      conn.setDoInput(true);
      conn.setUseCaches(false);
      conn.setRequestMethod(RequestMethod_post);
      conn.setRequestProperty("Connection", "Keep-Alive");
      conn.setRequestProperty(
          "User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
      conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
      conn.setRequestProperty("Charset", "UTF-8");
      OutputStream out = new DataOutputStream(conn.getOutputStream());
      if (textMap != null) {
        StringBuffer strBuf = new StringBuffer();
        Iterator iter = textMap.entrySet().iterator();
        while (iter.hasNext()) {
          Map.Entry entry = (Map.Entry) iter.next();
          String inputName = (String) entry.getKey();
          String inputValue = (String) entry.getValue();
          if (inputValue == null) {
            continue;
          }
          strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
          strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
          strBuf.append(inputValue);
        }
        out.write(strBuf.toString().getBytes("UTF-8"));
      }
      if (objMap != null) {
        Iterator iter = objMap.entrySet().iterator();
        while (iter.hasNext()) {
          Map.Entry entry = (Map.Entry) iter.next();
          String inputName = (String) entry.getKey();
          String inputValue = (String) entry.getValue();
          if (inputValue == null) {
            continue;
          }
          File file = new File(inputValue);
          String filename = file.getName();
          StringBuffer strBuf = new StringBuffer();
          strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
          strBuf.append(
              "Content-Disposition: form-data; name=\""
                  + inputName
                  + "\"; filename=\""
                  + filename
                  + "\"\r\n");
          strBuf.append("Content-Type:application/octet-stream" + "\r\n\r\n");
          out.write(strBuf.toString().getBytes());

          InputStream in = new URL(inputValue).openStream();
          int bytes = 0;
          byte[] bufferOut = new byte[1024];

          while ((bytes = in.read(bufferOut)) != -1) {
            out.write(bufferOut, 0, bytes);
          }
          in.close();
        }
      }
      byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
      out.write(endData);
      out.flush();
      out.close();
      // 流处理
      int responseCode = conn.getResponseCode();
      if (responseCode == 200) {
        // 读取返回数据
        StringBuffer strBuf = new StringBuffer();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

        String line = null;
        while ((line = reader.readLine()) != null) {
          strBuf.append(line).append("\n");
        }
        res = strBuf.toString();
        reader.close();
        reader = null;
      } else {
        // {"code":-1001,"msg":"invalid token","success":false}
        if (responseCode == 400) {
          return "{\"code\":-1001,\"msg\":\"invalid token\",\"success\":false}";
        }
        if (responseCode == 404) {
          return "{\"code\":404,\"msg\":\"404\",\"success\":false}";
        }

        StringBuffer error = new StringBuffer();
        BufferedReader bufferedReader =
            new BufferedReader(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
        String line1 = null;
        while ((line1 = bufferedReader.readLine()) != null) {
          error.append(line1).append("\n");
        }
        res = error.toString();
        bufferedReader.close();
        bufferedReader = null;
      }

    } catch (Exception e) {
      throw new RuntimeException("调用CA接口异常, 发送POST请求出错, " + e.getMessage());
    } finally {
      if (conn != null) {
        conn.disconnect();
        conn = null;
      }
    }
    res = jsonReplaceAll(res); // 替换
    return res;
  }

  // 解决PKIX path building failed问题，在代码中必须要忽略证书信任问题
  private static void trustAllHttpsCertificates() throws Exception {
    javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
    javax.net.ssl.TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, null);
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  }

  static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
      return null;
    }

    public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
      return true;
    }

    public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
      return true;
    }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
      return;
    }

    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
      return;
    }
  }

  public static String jsonReplaceAll(String json) {
    // idCard  bankCard
    json = json.replaceAll("valid_date", "validDate");
    // idCard
    json = json.replaceAll("id_card_number", "idCardNumber");
    // idCard
    json = json.replaceAll("issued_by", "issuedBy");

    return json;
  }

  public static String toBase64FromURL(String imgUrl) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
      URLDataSource urlDataSource = new URLDataSource(new URL(imgUrl));
      InputStream in = urlDataSource.getInputStream();
      byte[] bytes = new byte[in.available()];
      int len;
      while ((len = in.read(bytes)) != -1) {
        out.write(bytes, 0, len);
      }
    } catch (IOException e) {
      log.error("图片base64转码失败");
      return null;
    }
    String base64Encode = base64EncodeFromBytes(out.toByteArray());
    return base64Encode;
  }
  /**
   * base 64 encode
   *
   * @param bytes 待编码的byte[]
   * @return 编码后的base 64 code
   */
  public static String base64EncodeFromBytes(byte[] bytes) {
    return Base64.encodeBase64String(bytes);
  }

  public static void base64Decode(String str) {
    byte[] bytes = Base64.decodeBase64(str);
    try {
      OutputStream out = new FileOutputStream("D:\\work2.0\\getTF.pdf");
      out.write(bytes);
      out.flush();
      out.close();
    } catch (IOException e) {
      System.out.println("base64解码导出异常");
      e.printStackTrace();
    }
    System.out.println("base64解码导出成功");
  }

  //  public static void out(Object obj, String path) {
  //    try {
  //      File file = new File(path);
  //      if (file.exists()) {
  //        file.delete();
  //        file = new File(path);
  //      }
  //
  //      ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(file));
  //      oo.writeObject(obj);
  //      System.out.println("序列化成功！");
  //      oo.close();
  //    } catch (IOException e) {
  //      System.out.println("序列化异常: " + e);
  //    }
  //  }
}
